You can present the recommended user interface for selecting a volume by calling the CustomGetFile procedure and passing it the addresses of a custom file filter function and a dialog hook function. See "Selecting Volumes and Directories" for a description of the appearance and behavior of the volume selection dialog box.
The file filter function used to select volumes is quite simple; it ensures that only volumes, not files or directories, are listed in the dialog box displayed by CustomGetFile . Listing 3-16 defines a file filter function you can use to do this.
Listing 20 A file filter function that lists only volumes
FUNCTION MyCustomFileFilter (pb: CInfoPBPtr; myDataPtr: Ptr): Boolean;
CONST
kFolderBit = 4; {bit set in ioFlAttrib for a directory}
BEGIN {list volumes only}
MyCustomFileFilter := TRUE; {assume you don't list the item}
IF BTst(pb^.ioFlAttrib, kFolderBit) AND (pb^.ioDrParID = fsRtParID) THEN
MyCustomFileFilter := FALSE;
END;
The function MyCustomFileFilter inspects the appropriate bit in the file attributes ( ioFlAttrib ) field of the catalog information parameter block passed to it. If the directory bit is set, MyCustomFileFilter checks whether the parent directory ID of the directory is equal to fsRtParID , which is always the parent directory ID of a volume's root directory. If it is, the file filter function returns FALSE , indicating that the item should appear in the list of volumes; otherwise, the file filter function returns TRUE to exclude the item from the list.
A dialog hook function for handling the items in the volume selection dialog box is defined in Listing 3-21 .
Listing 21 Handling user selections in the volume selection dialog box
FUNCTION MyDlgHook (item: Integer; theDialog: DialogPtr; myDataPtr: Ptr):
Integer;
VAR
myType: Integer; {menu item selected}
myHandle: Handle; {needed for GetDItem}
myRect: Rect; {needed for GetDItem}
myName: Str255; {new title for Open button}
BEGIN
MyDlgHook := item; {default, except in special cases below}
IF GetWRefCon(WindowPtr(theDialog)) <> LongInt(sfMainDialogRefCon) THEN
Exit(MyDlgHook); {this function is only for main dialog box}
CASE item OF
sfHookFirstCall:
BEGIN
{Set button title and go to desktop.}
myName := 'Select';
GetDItem(theDialog, sfItemOpenButton, myType, myHandle, myRect);
SetCTitle(ControlHandle(myHandle), myName);
MyDlgHook := sfHookGoToDesktop;
END;
sfHookGoToDesktop: {map Cmd-D to a null event}
MyDlgHook := sfHookNullEvent;
sfHookChangeSelection:
MyDlgHook := sfHookGoToDesktop;
sfHookGoToNextDrive: {map Cmd-Left Arrow to a null event}
MyDlgHook := sfHookNullEvent;
sfHookGoToPrevDrive: {map Cmd-Right Arrow to a null event}
MyDlgHook := sfHookNullEvent;
sfItemOpenButton, sfHookOpenFolder:
MyDlgHook := sfItemOpenButton;
OTHERWISE
;
END;
END;
You can prompt the user to select a volume by calling the function DoGetVolume defined in Listing 3-22 .
Listing 22 Presenting the volume selection dialog box
FUNCTION DoGetVolume: StandardFileReply;
VAR
myReply: StandardFileReply;
myTypes: SFTypeList; {types of files to display}
myPoint: Point; {upper-left corner of box}
myNumTypes: Integer;
myModalFilter: ModalFilterYDProcPtr;
myActiveList: Ptr;
myActivateProc: ActivateYDProcPtr;
CONST
rGetVolumeDLOG = 129; {resource ID of custom dialog box}
BEGIN
myNumTypes := -1; {pass all types of files}
myPoint.h := -1; {center dialog box on screen}
myPoint.v := -1;
myModalFilter := NIL;
myActiveList := NIL;
myActivateProc := NIL;
CustomGetFile(@MyCustomFileFilter, myNumTypes, myTypes, myReply,
rGetVolumeDLOG, myPoint, @MyDlgHook, myModalFilter,
myActiveList, myActivateProc, @myReply);
DoGetVolume := myReply;
END;